package term.dept;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import term.dept.course.Course;

import exception.InvalidNameException;

/**
 * Represents a single department within a college.
 * Contains references to all courses within this department
 * and the department name and code.
 * @author sjp
 *
 */
public class Department {
	public static enum Code {
		ACC ("ACC", "Accounting"),
		BA ("BA", "Business Administration"),
		BE ("BE", "Biomedical Engineering"),
		BL ("BL", "Biology"),
		BUS ("BUS", "Business"),
		CE ("CE", "Civil Engineering"),
		CH ("CH", "Chemistry"),
		CM ("CM", "Chemical Engineering"),
		CMG ("CMG", "Construction Management"),
		CS ("CS", "Computer Science"),
		EC ("EC", "Economics"),
		ED ("ED", "Education"),
		EE ("EE", "Electrical Engineering"),
		EET ("EET", "Electrical Engineering Technology"),
		EH ("EH", "Exercise Science"),
		ENG ("ENG", "Engineering"),
		ENVE ("ENVE", "Environmental Engineering"),
		ESL ("ESL", "English as a Second Language"),
		FA ("FA", "Fine Arts"),
		FIN ("FIN", "Finance"),
		FW ("FW", "Forestry"),
		GE ("GE", "Geotechnical Engineering"),
		HU ("HU", "Humanities"),
		MA ("MA", "Mathematical Sciences"),
		MEEM ("MEEM", "Mechanical Engineering / Engineering Mechanics"),
		MET ("MET", "Mechanical Engineering Technology"),
		MGT ("MGT", "Management"),
		MIS ("MIS", "Management Information Systems"),
		MKT ("MKT", "Marketing"),
		MY ("MY", "Materials Science"),
		OSM ("OSM", "Operations Systems Management"),
		PH ("PH", "Physics"),
		PSY ("PSY", "Psychology"),
		SAT ("SAT", "Systems Administration"),
		SS ("SS", "Social Sciences"),
		SSE ("SSE", "Service Systems Engineering"),
		SU ("SU", "Surveying"),
		TE ("TE", "Technology"),
		UN ("UN", "University Wide");
		
		private String code, name;
		
		Code (String c, String n) {
			code = c;
			name = n;
		}

		/**
		 * @return the code
		 */
		public String getCode() {
			return code;
		}

		/**
		 * @return the name
		 */
		public String getName() {
			return name;
		}
		
		public static boolean isValid(String code) {
			for (Code c : values())
				if (c.getCode().equalsIgnoreCase(code))
					return true;
			
			return false;
		}
		
		public static Code getCode(String s) {
			for (Code c : values())
				if (c.getCode().equalsIgnoreCase(s))
					return c;
			
			return null;
		}
		
		public String toString() {
			return getCode();
		}
	}
	
	
	/**
	 * Department code. eg MA
	 */
	private Code code;
	
	/**
	 * Courses within this department
	 */
	private Map<Integer,Course> courses;

	/**
	 * Creates a new Department with the given code and name
	 * @param c code
	 * @param n name
	 */
	public Department(Code c) {
		code = c;
		courses = new HashMap<Integer,Course>();
	}
	
	public static HashMap<Code,Department> initDepts() {
		HashMap<Code,Department> depts = new HashMap<Code,Department>(Code.values().length);
		for (Code c : Code.values()) {
			Department d = new Department(c);
			depts.put(c,d);
		}
		
		return depts;
	}
	
	/**
	 * @return department code
	 */
	public Code getCode() {return code;}
	
	/**
	 * @return department name
	 */
	public String getName() {return code.getName();}
	
	/**
	 * Returns the Course object associated with the given id.
	 * If it does not exist, throws InvalidNameException
	 * @param id course id
	 * @return course
	 * @throws InvalidNameException if course "id" does not exist
	 */
	public Course getCourse(int id){
		if (courses.containsKey(id))
			return courses.get(id);
		else
			return null;
	}
	
	/**
	 * @return the map of strings to courses.
	 */
	public Map<Integer,Course> getCourses() {return courses;}
	
	/**
	 * Adds a NEW course to this department or returns the course if it exists.
	 * @param num course number
	 * @param name course name
	 * @return new course
	 */
	public Course addCourse(int num, String name) {
		if (courses.containsKey(name))
			return courses.get(name);
		else {
			Course c = new Course(this,num,name);
			courses.put(num, c);
			return c;
		}
	}
	
	/**
	 * Adds an EXISTING course to this department
	 * @param num course number
	 * @param name course name
	 * @return new course
	 * @throws InvalidNameException if the course already exists.
	 */
	public Course addCourse(Course c) throws InvalidNameException {
		if (courses.containsKey(c.getName()))
			throw new InvalidNameException("Add Course: id \""+c.getName()+"\" already exists.");
		else {
			courses.put(c.getNumber(), c);
			return c;
		}
	}
	
	public String toString() {return code.code;}
}
